#include "ActionSharePoster.h"
#include "json.h"
#include "util.h"
#include "streamdata.h"
#include "agency_event_service.h"
#include "agencyeventmgr.h"
#include "sharepostermgr.h"
#include "9200_agency_event_api.pb.h"


static std::map<std::string,std::string> http_json_heads = {{"Content-Type","application/json"}};

static bool __init__ = ActionSharePoster::Init();

bool ActionSharePoster::Init()
{
    Ctx.msg_router.BindMsg(agency_event_api::AGENCY_EVENT_API_MSGID_SHARE_POSTER_REQ, ActionSharePoster::Handle);
    AgencyEventService::Instance()->ListenOnAgencyEventGet(AgencyEventService::SHARE_POSTER, ActionSharePoster::OnAgencyEventGet);

    return true;
}

void ActionSharePoster::Handle(MsgData&& msg_data)
{
    agency_event_api::SharePosterReq req;
    agency_event_api::SharePosterResp resp;

    do {
        if (!req.ParseFromArray(msg_data.data.data(), msg_data.data.size()))
        {
            resp.set_errorcode(agency_event_api::ErrorCode::DataParseErr);
            log_error("parser agency_event_api::SharePosterReq failed");
            break;
        }
        log_debug("req:%s", req.ShortDebugString().c_str());

        // auto share_poster = SharePosterMgr::Instance()->Get(req.uid());
        // if (share_poster != nullptr)
        // {
        //     resp.mutable_data()->CopyFrom(*share_poster);
        //     resp.set_errorcode(agency_event_api::ErrorCode::Success);
        //     break;
        // }

        stAgencyEvent* st_agencyevent = AgencyEventMgr::Instance()->Get(req.agencyid());
        if (st_agencyevent != nullptr)
        {
            Request(*st_agencyevent, req.trans(), msg_data.svtype, msg_data.svid, msg_data.uuid, 
                req.uid(), req.agencyid(), req.game(), req.appid(), req.sharetype(), req.username(), req.child_type());
        }
        else
        {
            StreamData stream_data;
            StreamDataWriter writer(stream_data);
            writer.WriteShort(msg_data.svtype);
            writer.WriteInt(msg_data.svid);
            writer.WriteInt(msg_data.uuid);
            writer.WriteString(req.trans());
            writer.WriteInt(req.agencyid());
            writer.WriteInt(req.game());
            writer.WriteInt(req.appid());
            writer.WriteInt(req.sharetype());
            writer.WriteInt(req.uid());
            writer.WriteString(req.username());
            writer.WriteInt(req.child_type());

            if (!AgencyEventService::Instance()->HandleGetAgencyEvent(req.agencyid(), std::move(stream_data.Data()), AgencyEventService::SHARE_POSTER))
            {
                resp.set_errorcode(agency_event_api::ErrorCode::AgencyGetErr);
                log_error("HandleGetAgencyEvent failed,agencyid:%u", req.agencyid());
                break;
            }
        }
        return;
    } while(false);

    // 回包
    resp.set_uid(req.uid());
    resp.set_game(req.game());
    resp.set_appid(req.appid());
    resp.set_sharetype(req.sharetype());
    resp.set_child_type(req.child_type());
    resp.set_trans(req.trans());
    Ctx.host->MtSendtoOneSrv(agency_event_api::AGENCY_EVENT_API_MSGID_SHARE_POSTER_RESP, &resp, msg_data.svtype, msg_data.svid, false, msg_data.uuid);
}

void ActionSharePoster::OnAgencyEventGet(std::int32_t err_code, stAgencyEvent* agencyevent, std::string&& trans)
{
    StreamData stream_data(std::move(trans));
    StreamDataReader reader(stream_data);
    std::uint16_t svtype = reader.ReadShort();
    std::uint32_t svid = reader.ReadInt();
    std::uint32_t uuid = reader.ReadInt();
    trans = reader.ReadString();
    std::uint32_t agencyid = reader.ReadInt();
    std::uint32_t game = reader.ReadInt();
    std::uint32_t appid = reader.ReadInt();
    std::uint32_t sharetype = reader.ReadInt();
    std::uint32_t uid = reader.ReadInt();
    std::string username = reader.ReadString();
    std::uint32_t child_type = reader.ReadInt();

    agency_event_api::SharePosterResp resp;
    do
    {
        if (err_code != 0)
        {
            resp.set_errorcode(agency_event_api::ErrorCode::AgencyGetErr);
            log_error("get agency info failed,agencyid:%u,err_code:%d", agencyid, err_code);
            break;
        }
        if (agencyevent == nullptr)
        {
            resp.set_errorcode(agency_event_api::ErrorCode::AgencyGetErr);
            log_error("agency is nullptr,agencyid:%u,err_code:%d", agencyid, err_code);
            break;
        }
    
        Request(*agencyevent, trans, svtype, svid, uuid, uid, agencyid, game, appid, sharetype, username, child_type);

        return;
    } while(false);

    if (resp.errorcode() != 0)
    {
        // 回包
        resp.set_uid(uid);
        resp.set_game(game);
        resp.set_appid(appid);
        resp.set_sharetype(sharetype);
        resp.set_trans(trans);
        resp.set_child_type(child_type);
        Ctx.host->MtSendtoOneSrv(agency_event_api::AGENCY_EVENT_API_MSGID_SHARE_POSTER_RESP, &resp, svtype, svid, false, uuid);
    }
}

void ActionSharePoster::Request(const stAgencyEvent& agencyevent, const std::string& trans
        ,std::uint16_t svtype, std::uint32_t svid, std::uint32_t uuid, 
        const std::uint32_t& uid, const std::uint32_t& agencyid, const std::uint32_t& game, 
        const std::uint32_t& appid, const std::uint32_t& sharetype, const std::string& username, const std::uint32_t& child_type)
{
    agency_event_api::SharePosterResp resp;
    do
    {
        if (agencyevent.state != 1)
        {
            resp.set_errorcode(agency_event_api::ErrorCode::AccessLimitErr);
            log_error("agency state not valid, %s", agencyevent.ToString().c_str());
            break;
        }
        // if (agencyevent.gamelist.find(game) == agencyevent.gamelist.end())
        // {
        //     resp.set_errorcode(agency_event_api::ErrorCode::GameLimitErr);
        //     log_error("game:%u not support, %s", game, agencyevent.ToString().c_str());
        //     break;
        // }

        std::string req_id = GenTransId();
        std::uint64_t reqtime = CTools::GetUnixTime();

        Json::Value http_req;
        http_req["reqId"] = req_id;
        http_req["reqtime"] = Json::Int64(reqtime);
        http_req["username"] = username;
        http_req["game"] = game;
        http_req["appid"] = appid;
        http_req["sharetype"] = sharetype;
        http_req["childtype"] = child_type;

        std::string json_string = CTools::ToStr(http_req);
        std::string url = agencyevent.call_url + "/SharePoster";

        std::uint32_t event_id = 0;
        // 请求http网络
        if (!Ctx.msg_router.sendHttpPOST(url, json_string, http_json_heads, event_id) || (event_id == 0))
        {
            resp.set_errorcode(agency_event_api::ErrorCode::SendPostErr);
            log_error("net post failed,url:%s,param:%s", url.c_str(), json_string.c_str());
            break;
        }
        // 添加回调监听
        Ctx.msg_router.AddCurlEvent(event_id, [svtype, svid, uuid, trans=std::move(trans),appid,sharetype,
            url=std::move(url), json_string= std::move(json_string), uid, agencyid, game, reqtime, child_type] (std::string& body, bool is_ok){
            agency_event_api::SharePosterResp resp;
            Json::Value http_resp;
            
            std::uint64_t resptime = CTools::GetUnixTime();

            log_info("url:%s,req:%s,resp:%s,reqtime:%llu,resptime:%llu", 
                url.c_str(), json_string.c_str(), body.c_str(), reqtime, resptime);

            do
            {
                // 网络错误
                if (!is_ok)
                {
                    resp.set_errorcode(agency_event_api::ErrorCode::RespTimeout);
                    log_error("time out,url:%s,param:%s", url.c_str(), json_string.c_str());
                    break;
                }
                
                // 解析返回格式
                if (!CTools::FromStr(http_resp, body))
                {
                    // resp.set_errorcode(agency_event_api::ErrorCode::DataParseErr);
                    resp.set_errorcode(agency_event_api::ErrorCode::RespTimeout);
                    log_error("resp from json failed, body:%s ,url:%s,param:%s", body.c_str(), url.c_str(), json_string.c_str());
                    break;
                }
                if (!http_resp.isMember("errorCode") || !http_resp["errorCode"].isInt())
                {
                    resp.set_errorcode(agency_event_api::ErrorCode::InvaildParam);
                    log_error("response param errorcode miss, body:%s ,url:%s,param:%s", body.c_str(), url.c_str(), json_string.c_str());
                    break;
                }
                if (!http_resp.isMember("data") || !http_resp["data"].isObject())
                {
                    resp.set_errorcode(agency_event_api::ErrorCode::InvaildParam);
                    log_error("response param data miss, body:%s ,url:%s,param:%s", body.c_str(), url.c_str(), json_string.c_str());
                    break;
                }
                if (!http_resp.isMember("invite_code") || !http_resp["invite_code"].isString())
                {
                    // resp.set_errorcode(agency_event_api::ErrorCode::InvaildParam);
                    log_error("response param invite_code miss, body:%s ,url:%s,param:%s", body.c_str(), url.c_str(), json_string.c_str());
                    // break;// 兼容别的封盘 没更新该字段
					http_resp["invite_code"] = "-1";
                }

                if (http_resp["errorCode"].asInt() != 0) 
                {
                   resp.set_errorcode(http_resp["errorCode"].asInt());
                   break;
                }
                // 缓存玩家分享信息
                agency_event_api::SharePoster share_poster;

                auto &share_json = http_resp["data"];
                if (share_json.isMember("title") && share_json["title"].isString())
                {
                    share_poster.set_title(share_json["title"].asString());
                }
                if (share_json.isMember("share_url") && share_json["share_url"].isString())
                {
                    share_poster.set_share_url(share_json["share_url"].asString());
                }
                if (share_json.isMember("telegram") && share_json["telegram"].isString())
                {
                    share_poster.set_telegram(share_json["telegram"].asString());
                }
                if (share_json.isMember("whatsapp") && share_json["whatsapp"].isString())
                {
                    share_poster.set_whatsapp(share_json["whatsapp"].asString());
                }
                if (share_json.isMember("poster") && share_json["poster"].isArray())
                {
                    for (unsigned int j = 0; j < share_json["poster"].size(); j++)
                    {
                        if (share_json["poster"][j].isMember("id") && share_json["poster"][j]["id"].isInt()
                            && share_json["poster"][j].isMember("url") && share_json["poster"][j]["url"].isString())
                        {
                            auto poster = share_poster.add_poster();
                            poster->set_id(share_json["poster"][j]["id"].asInt());
                            poster->set_url(share_json["poster"][j]["url"].asString());
                        }
                    }
                }
                resp.mutable_data()->CopyFrom(share_poster);
                SharePosterMgr::Instance()->Set(uid, std::move(share_poster));
            } while (false);

            // 回包
            resp.set_uid(uid);
            resp.set_game(game);
            resp.set_appid(appid);
            resp.set_sharetype(sharetype);
            resp.set_trans(std::move(trans));
            resp.set_invite_code(http_resp["invite_code"].asString());
            resp.set_child_type(child_type);
            log_debug("resp:%s", resp.ShortDebugString().c_str());
            Ctx.host->MtSendtoOneSrv(agency_event_api::AGENCY_EVENT_API_MSGID_SHARE_POSTER_RESP, &resp, svtype, svid, false, uuid);
        });

        return;
    } while(false);

    if (resp.errorcode() != 0)
    {
        // 回包
        resp.set_uid(uid);
        resp.set_game(game);
        resp.set_appid(appid);
        resp.set_sharetype(sharetype);
        resp.set_trans(trans);
        resp.set_child_type(child_type);
        Ctx.host->MtSendtoOneSrv(agency_event_api::AGENCY_EVENT_API_MSGID_SHARE_POSTER_RESP, &resp, svtype, svid, false, uuid);
    }
}
